interface DataItem {
  id: string;
  parentId: string;
  [key: string]: unknown; // 对于可能有所不同的其他属性
}
/**
 * 将扁平数据结构转换为树形结构。
 *
 * 此函数接受一个扁平的数据数组，并基于指定的id、parentId以及children字段将其转换为树形结构的数组。
 * 它首先创建一个映射来跟踪每个节点的子节点，然后遍历数据以填充这个映射。
 * 最后，它遍历数据第二次来构建最终的树形结构，只包括顶级节点，每个节点都递归地包含其子节点。
 *
 * @template T extends DataItem 表示数据项的类型，必须扩展自DataItem接口。
 * @param {Array<DataItem>} data 扁平数据数组。
 * @param {string} [id='id'] 用作唯一标识符的属性名，默认为'id'。
 * @param {string} [parentId='parentId'] 用来指示父节点的属性名，默认为'parentId'。
 * @param {string} [children='children'] 子节点数组将被附加到父节点的此属性下，默认为'children'。
 * @returns {Array<T>} 树形结构的数组。
 *
 * @example
 * // 示例数据
 * const sampleData = [
 *   { id: '1', parentId: '', name: '根节点' },
 *   { id: '2', parentId: '1', name: '子节点1' },
 *   { id: '3', parentId: '1', name: '子节点2' },
 *   { id: '4', parentId: '2', name: '孙节点1' },
 *   { id: '5', parentId: '2', name: '孙节点2' }
 * ];
 *
 * // 调用函数
 * const tree = treeData(sampleData);
 *
 * // 输出结果
 * console.log(tree);
 * // [
 * //   {
 * //     id: '1',
 * //     parentId: '',
 * //     name: '根节点',
 * //     children: [
 * //       {
 * //         id: '2',
 * //         parentId: '1',
 * //         name: '子节点1',
 * //         children: [
 * //           { id: '4', parentId: '2', name: '孙节点1' },
 * //           { id: '5', parentId: '2', name: '孙节点2' }
 * //         ]
 * //       },
 * //       {
 * //         id: '3',
 * //         parentId: '1',
 * //         name: '子节点2'
 * //       }
 * //     ]
 * //   }
 * // ]
 */
export function treeData<T extends DataItem>(data: Array<DataItem>, id: string = 'id', parentId: string = 'parentId', children: string = 'children'): Array<T> {
  const childrenListMap: Record<string, Array<DataItem>> = {};
  const nodeIds: Record<string, DataItem> = {};
  const tree: Array<T> = [];

  data.forEach((d) => {
    const parentIdValue = d[parentId] as string; // 将 parentIdValue 的类型断言为字符串
    if (!childrenListMap[parentIdValue]) {
      childrenListMap[parentIdValue] = [];
    }
    nodeIds[d[id] as string] = d; // 同时将 d[id] 的类型断言为字符串
    childrenListMap[parentIdValue].push(d);
  });

  data.forEach((d) => {
    if (!nodeIds[d[parentId] as string]) {
      tree.push(d as T);
    }
  });

  const assignChildren = (node: DataItem) => {
    if (childrenListMap[node[id] as string]) {
      node[children] = childrenListMap[node[id] as string];
      (node[children] as Array<DataItem>).forEach(assignChildren); // 对 Array<DataItem>的类型断言
    }
  };

  tree.forEach(assignChildren);

  return tree;
}
export default treeData;
